//
//  NSArray+MOCrashHandle.m
//  WCImApp
//
//  Created by MOiMac on 2019/8/30.
//  Copyright © 2019 WCImApp. All rights reserved.
//

/*
 
 因Runtime的这个文件需要通过mrc管理:
 一般项目都是 ARC 模式，需要单独问Runtime的这个问题添加MRC支持，
 Build Phases -> Compile Sources找到文件设置 -fno-objc-arc 标签。
 如果项目是MRC 模式，则为 ARC 模式的代码文件加入 -fobjc-arc 标签.
 
 */

#import "NSArray+MOCrashHandle.h"
#import "NSObject+MOSwizzleMethod.h"
#import <objc/runtime.h>
#import "NSObject+MOSwizzleMethod.h"

@implementation NSArray (MOCrashHandle)


+(void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        @autoreleasepool {
//#if !DEBUG
            [objc_getClass("__NSArray0") swizzleMethod:@selector(objectAtIndex:) swizzledSelector:@selector(emptyObjectIndex:)];
            [objc_getClass("__NSSingleObjectArrayI") swizzleMethod:@selector(objectAtIndex:) swizzledSelector:@selector(singleObjectIndex:)];
            [objc_getClass("__NSArrayI") swizzleMethod:@selector(objectAtIndex:) swizzledSelector:@selector(arrObjectIndex:)];
            [objc_getClass("__NSPlaceholderArray") swizzleMethod:@selector(initWithObjects:count:) swizzledSelector:@selector(mo_initWithObjects:count:)];
            
            //数组初始化类
            [self swizzleInstanceMethodWithClass:NSClassFromString(@"__NSPlaceholderArray") originalSel:@selector(objectAtIndex:) swizzledSel:@selector(af_NSPlaceholderArray_objectAtIndex:)];
            [self swizzleInstanceMethodWithClass:NSClassFromString(@"__NSPlaceholderArray") originalSel:@selector(objectAtIndexedSubscript:) swizzledSel:@selector(af_objectAtIndexedSubscript_NSPlaceholderArray:)];
            //空元素数组类，空数组
            [self swizzleInstanceMethodWithClass:NSClassFromString(@"__NSArray0") originalSel:@selector(objectAtIndexedSubscript:) swizzledSel:@selector(af_objectAtIndexedSubscript_NSArray0:)];
            //单元素数组类，一个元素的数组
            [self swizzleInstanceMethodWithClass:NSClassFromString(@"__NSSingleObjectArrayI") originalSel:@selector(objectAtIndexedSubscript:) swizzledSel:@selector(af_objectAtIndexedSubscript_NSSingleObjectArrayI:)];
            //多元素数组类，两个元素以上的数组
            [self swizzleInstanceMethodWithClass:NSClassFromString(@"__NSArrayI") originalSel:@selector(objectAtIndexedSubscript:) swizzledSel:@selector(af_objectAtIndexedSubscript_NSArrayI:)];
//            [self swizzleInstanceMethodWithClass:NSClassFromString(@"__NSArrayI") originalSel:@selector(getObjects:range:) swizzledSel:@selector(mo_getObjects:range:)];

//#endif
        }
    });
}

//- (instancetype)mo_getObjects:(id  _Nonnull const [])objects range:(NSRange)aRange {
//
//    return [self mo_getObjects:objects range:aRange];
//}

- (instancetype)mo_initWithObjects:(id  _Nonnull const [])objects count:(NSUInteger)cnt
{
     id safeObjects[cnt];
     NSUInteger j = 0;
     for (NSUInteger i = 0; i < cnt; i++) {
          id obj = objects[i];
          if (!obj) {
              @try {
                  //MO_Update
//                  Buly上报
                  [QAModuleService buglyReportName:@"数组越界" reason:@"mo_initWithObjects" extraInfo:@{@"callstack":[NSThread callStackSymbols]}];
              } @catch (NSException *exception) {
                  
              } @finally {
                  
              }
               continue;
          }
          safeObjects[j] = obj;
          j++;
     }
     return [self mo_initWithObjects:safeObjects count:j];
}
- (id)emptyObjectIndex:(NSInteger)index {
    return nil;
}

- (id)singleObjectIndex:(NSInteger)index {
    if (index >= self.count || index < 0) {
        @try {
            return [self singleObjectIndex:index];
        } @catch (NSException *exception) {
            //MO_Update
            [QAModuleService buglyReportName:@"数组越界" reason:@"singleObjectIndex" extraInfo:@{@"exception":exception,@"callstack":exception.callStackSymbols}];
            return nil;
        } @finally {
            
        }
        
    } else {
        return [self singleObjectIndex:index];
    }
}

- (id)arrObjectIndex:(NSInteger)index {
    
    if (index > self.count - 1 || !self.count || index < 0) {
        @try {
            return [self arrObjectIndex:index];
        } @catch (NSException *exception) {
            //MO_Update
            [QAModuleService buglyReportName:@"数组越界" reason:@"arrObjectIndex" extraInfo:@{@"exception":exception,@"callstack":exception.callStackSymbols}];

            return nil;
        } @finally {
            
        }
    } else{
        return [self arrObjectIndex:index];
    }
}





#pragma mark - 获取数组元素  防止越界
- (id)af_NSPlaceholderArray_objectAtIndex:(NSUInteger)index {
    if (index < self.count)  return [self af_NSPlaceholderArray_objectAtIndex:index];
    @try {
        return [self af_NSPlaceholderArray_objectAtIndex:index];
    } @catch (NSException *exception) {
        //MO_Update
        [QAModuleService buglyReportName:@"数组越界" reason:@"af_NSPlaceholderArray_objectAtIndex" extraInfo:@{@"exception":exception,@"callstack":exception.callStackSymbols}];

        return nil;
    }
}
- (id)af_objectAtIndexedSubscript_NSPlaceholderArray:(NSUInteger)idx {
    if (idx < self.count)  return [self af_objectAtIndexedSubscript_NSPlaceholderArray:idx];
    @try {
        return [self af_objectAtIndexedSubscript_NSPlaceholderArray:idx];
    } @catch (NSException *exception) {
        //MO_Update
        [QAModuleService buglyReportName:@"数组越界" reason:@"objectAtIndexedSubscript_NSPlaceholderArray" extraInfo:@{@"exception":exception,@"callstack":exception.callStackSymbols}];
        return nil;
    }
}

- (id)af_objectAtIndexedSubscript_NSArray0:(NSUInteger)idx {
    if (idx < self.count)  return [self af_objectAtIndexedSubscript_NSArray0:idx];
    @try {
        return [self af_objectAtIndexedSubscript_NSArray0:idx];
    } @catch (NSException *exception) {
        //MO_Update
        [QAModuleService buglyReportName:@"数组越界" reason:@"af_objectAtIndexedSubscript_NSArray0" extraInfo:@{@"exception":exception,@"callstack":exception.callStackSymbols}];

        return nil;
    }
}

- (id)af_objectAtIndexedSubscript_NSSingleObjectArrayI:(NSUInteger)idx {
    if (idx < self.count)  return [self af_objectAtIndexedSubscript_NSSingleObjectArrayI:idx];
    @try {
        return [self af_objectAtIndexedSubscript_NSSingleObjectArrayI:idx];
    } @catch (NSException *exception) {
        //MO_Update
        [QAModuleService buglyReportName:@"数组越界" reason:@"af_objectAtIndexedSubscript_NSSingleObjectArrayI" extraInfo:@{@"exception":exception,@"callstack":exception.callStackSymbols}];

        return nil;
    }
}

- (id)af_objectAtIndexedSubscript_NSArrayI:(NSUInteger)idx {
    if (idx < self.count)  return [self af_objectAtIndexedSubscript_NSArrayI:idx];
    @try {
        return [self af_objectAtIndexedSubscript_NSArrayI:idx];
    } @catch (NSException *exception) {
        //MO_Update
        [QAModuleService buglyReportName:@"数组越界" reason:@"af_objectAtIndexedSubscript_NSArrayI" extraInfo:@{@"exception":exception,@"callstack":exception.callStackSymbols}];

        return nil;
    }
}

@end




@implementation NSMutableArray (MOCrashHandle)

+ (void)load {

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        [self swizzleInstanceMethodWithClass:NSClassFromString(@"__NSArrayM") originalSel:@selector(addObject:) swizzledSel:@selector(af_addObject:)];
        [self swizzleInstanceMethodWithClass:NSClassFromString(@"__NSArrayM") originalSel:@selector(insertObject:atIndex:) swizzledSel:@selector(af_insertObject:atIndex:)];
        [self swizzleInstanceMethodWithClass:NSClassFromString(@"__NSArrayM") originalSel:@selector(removeObject:) swizzledSel:@selector(af_removeObject:)];
        [self swizzleInstanceMethodWithClass:NSClassFromString(@"__NSArrayM") originalSel:@selector(replaceObjectAtIndex:withObject:) swizzledSel:@selector(af_replaceObjectAtIndex:withObject:)];
        [self swizzleInstanceMethodWithClass:NSClassFromString(@"__NSArrayM") originalSel:@selector(setObject:atIndexedSubscript:) swizzledSel:@selector(mo_setObject:atIndexedSubscript:)];
        
//        [self swizzleInstanceMethodWithClass:NSClassFromString(@"__NSArrayM") originalSel:@selector(removeObjectAtIndex:) swizzledSel:@selector(af_removeObjectAtIndex:)];

        
        //        if (iOS11) {
            [self swizzleInstanceMethodWithClass:NSClassFromString(@"__NSArrayM") originalSel:@selector(objectAtIndex:) swizzledSel:@selector(af_NSArrayM_objectAtIndex:)];
            [self swizzleInstanceMethodWithClass:NSClassFromString(@"__NSArrayM") originalSel:@selector(objectAtIndexedSubscript:) swizzledSel:@selector(af_objectAtIndexedSubscript_NSArrayM:)];
            [self swizzleInstanceMethodWithClass:NSClassFromString(@"__NSArrayI") originalSel:@selector(objectAtIndexedSubscript:) swizzledSel:@selector(af_objectAtIndexedSubscript_NSArrayI:)];

//        }
    });
}

//- (id)af_objectAtIndexedSubscript_NSArrayI:(NSUInteger)idx {
//    if (idx < self.count)  return [self af_objectAtIndexedSubscript_NSArrayI:idx];
//    @try {
//        return [self af_objectAtIndexedSubscript_NSArrayI:idx];
//    } @catch (NSException *exception) {
//        [MOXLogUntil LogWarningWithString:@"objectAtIndexedSubscript_NSArrayI 数组越界了 %@",exception];
//        return nil;
//    }
//}


- (id)af_NSArrayM_objectAtIndex:(NSUInteger)index {
    if (index < self.count)  return [self af_NSArrayM_objectAtIndex:index];
    @try {
        return [self af_NSArrayM_objectAtIndex:index];
    } @catch (NSException *exception) {
        //MO_Update
        [QAModuleService buglyReportName:@"数组越界" reason:@"af_NSArrayM_objectAtIndex" extraInfo:@{@"exception":exception,@"callstack":exception.callStackSymbols}];

        return nil;
    }
}
- (id)af_objectAtIndexedSubscript_NSArrayM:(NSUInteger)idx {
    if (idx < self.count)  return [self af_objectAtIndexedSubscript_NSArrayM:idx];
    @try {
        return [self af_objectAtIndexedSubscript_NSArrayM:idx];
    } @catch (NSException *exception) {
        //MO_Update
        [QAModuleService buglyReportName:@"数组越界" reason:@"af_objectAtIndexedSubscript_NSArrayM" extraInfo:@{@"exception":exception,@"callstack":exception.callStackSymbols}];

        return nil;
    }
}



//添加数组元素
- (void)af_addObject:(id)anObject {
    if (anObject) {
        [self af_addObject:anObject];
    } else {
        @try {
            [self af_addObject:anObject];
        } @catch (NSException *exception) {
            //MO_Update
            [QAModuleService buglyReportName:@"数组越界" reason:@"af_addObject" extraInfo:@{@"exception":exception,@"callstack":exception.callStackSymbols}];

        }
    }
}

- (void)af_insertObject:(id)anObject atIndex:(NSUInteger)index {
    if (anObject) {
        if (index > self.count) index = self.count;
        [self af_insertObject:anObject atIndex:index];
    } else {
        @try {
            [self af_insertObject:anObject atIndex:index];
        } @catch (NSException *exception) {
//            [MOXLogUntil LogWarningWithString:@"insertObject:atIndex: 数组插入空元素 %@",exception];
            //MO_Update
          [QAModuleService buglyReportName:@"数组越界" reason:@"insertObject:atIndex: 数组插入空元素" extraInfo:@{@"array":self,@"exception":exception,@"callstack":exception.callStackSymbols,@"callstack":exception.callStackSymbols}];

        }
    }
}


//删除数组
- (void)af_removeObject:(id)anObject {
    if (anObject) {
        [self af_removeObject:anObject];
    } else {
        @try {
            [self af_removeObject:anObject];
        } @catch (NSException *exception) {
            //MO_Update
            [QAModuleService buglyReportName:@"数组越界" reason:@"af_removeObject: 数组删除空元素" extraInfo:@{@"exception":exception,@"callstack":exception.callStackSymbols}];

        }
    }
}

- (void)mo_setObject:(id)obj atIndexedSubscript:(NSUInteger)idx {
    if (obj && idx <= self.count) {
        [self mo_setObject:obj atIndexedSubscript:idx];
    } else {
        @try {
            [self mo_setObject:obj atIndexedSubscript:idx];
        } @catch (NSException *exception) {
            //MO_Update
            [QAModuleService buglyReportName:@"数组越界" reason:@"mo_setObject:atIndexedSubscript 数组删除空元素" extraInfo:@{@"exception":exception,@"callstack":exception.callStackSymbols}];

        }
    }
}

//更新
- (void)af_replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject {
    if(index < self.count && anObject) {
        [self af_replaceObjectAtIndex:index withObject:anObject];
    } else {
        @try {
            [self af_replaceObjectAtIndex:index withObject:anObject];
        } @catch (NSException *exception) {
            //MO_Update
            [QAModuleService buglyReportName:@"数组越界" reason:@"af_replaceObjectAtIndex:withObject 数组替换" extraInfo:@{@"exception":exception,@"callstack":exception.callStackSymbols}];

        }
    }
}

//- (void)af_removeObjectAtIndex:(NSUInteger)index{
//    if (index >= self.count) {
//        NSString *errorInfo = [NSString stringWithFormat:@"*** -[__NSArrayM removeObjectsInRange:]: range {%ld, 1} extends beyond bounds [0 .. %ld]",(unsigned long)index,(unsigned long)self.count];
//        [MOXLogUntil LogWarningWithString:@"replaceObjectAtIndex: 数组移除 %@",errorInfo];
//        return;
//    }
//    [self af_removeObjectAtIndex:index];
//}

@end






